package com.qf.mybatis01.utils;

import com.qf.mybatis01.dao.UserDao;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MybatisUtils {

    // 单例
    private static SqlSessionFactory sqlSessionFactory ;

    // 线程本地缓存，里面存放该线程创建过 的SqlSession对象
    private static ThreadLocal<SqlSession> cache = new ThreadLocal<SqlSession>();

    static {
        // 初始化 sqlSessionFactory
        final SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        try {
            final InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    // 获取 dao层对象的方法
    public static <T> T getMapper(Class<T> clazz){
         SqlSession sqlSession =  getSqlSessoin();
         return sqlSession.getMapper(clazz);
    }

    /**
     * 该方法需要确保同一个线程在调用时，能够拿到同一个sqlsession
     * 只有这样，数据库事务才可以控制
     * @return
     */
    private static SqlSession getSqlSessoin() {

        // 需要先从缓存中查找一下是否已经有了 SqlSession 对象，如果有则直接使用
        SqlSession sqlSession = cache.get();
        if (sqlSession==null){ // 线程第一调用该方法获取sqlSession
            sqlSession = sqlSessionFactory.openSession();
            // 放入线程本地缓存中
            cache.set(sqlSession);
        }

        return sqlSession;
    }

    /**
     * 提交事务
     */
    public static void commit(){
        final SqlSession sqlSessoin = getSqlSessoin();
        sqlSessoin.commit();
        closeSqlSession();
    }

    /**
     * 回滚事务
     */
    public static void rollback(){
        final SqlSession sqlSessoin = getSqlSessoin();
        sqlSessoin.rollback();
        closeSqlSession();
    }


    /**
     * 关闭sqlSession
     * 注意：要把 cache 中的SqlSession对象清掉
     */
    private static void closeSqlSession() {
        final SqlSession sqlSessoin = getSqlSessoin();
        sqlSessoin.close();
        cache.remove();
    }


}
